package com.hilin.common.common.aop;

import com.hilin.common.util.AssertUtils;
import com.hilin.common.util.EntityUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.event.Level;

import java.lang.reflect.Method;

@Slf4j
@Aspect
public class MethodLogAspect {

    private static final String LOG_FORMAT = "请求方法:{}  请求参数:{}  返回结果:{}";

    @Pointcut("@annotation(com.hilin.common.common.aop.LogAnno)")
    public void methodBefore() {
    }

    @AfterReturning(returning = "result", value = "methodBefore()")
    public void after(JoinPoint joinPoint, Object result) {
        try {
            Method method = getMethod(joinPoint);
            LogAnno logAnno = method.getAnnotation(LogAnno.class);
            if (logAnno != null) {
                log(logAnno.value(),
                        method,
                        EntityUtils.toJsonString(joinPoint.getArgs()),
                        EntityUtils.toJsonString(result));
            }
        } catch (Exception ignored) {
        }
    }

    private void log(Level level, Object... params) {
        if (Level.DEBUG.toString().equals(level.toString())) {
            log.debug(LOG_FORMAT, params);
        } else if (Level.INFO.toString().equals(level.toString())) {
            log.info(LOG_FORMAT, params);
        } else if (Level.TRACE.toString().equals(level.toString())) {
            log.trace(LOG_FORMAT, params);
        } else if (Level.WARN.toString().equals(level.toString())) {
            log.warn(LOG_FORMAT, params);
        } else if (Level.ERROR.toString().equals(level.toString())) {
            log.error(LOG_FORMAT, params);
        }
    }

    private Method getMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        if (!(signature instanceof MethodSignature)) {
            AssertUtils.throwEx("该注解仅用于方法");
        }
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }
}
